package com.learn.english.utils;



import com.learn.english.constants.JwtConstants;
import com.learn.english.domain.LoginUserVO;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Map;

/**
 * @author TISNIW
 * @version 1.0
 * @date 2025/5/1 17:02
 * @desc jwt工具类 + redis缓存token
 */
@Component
public class JwtUtils {

    // 使用 JJWT 工具类生成一个符合 HS512 要求的密钥（至少 512 bits）
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(JwtConstants.SECRET.getBytes());

    /**
     * 生成令牌并写入 Redis 缓存
     *
     * @param user 数据
     * @return 令牌
     */
    public static String createToken(LoginUserVO user) {
        Map<String, Object> claims = Map.of(
                JwtConstants.CLAIM_USER_ID, user.getId(),
                JwtConstants.CLAIM_USERNAME, user.getUsername(),
                JwtConstants.CLAIM_USER_KEY, JsonUtils.writeValueAsString(user)
        );

        String token = Jwts.builder()
                .claims(claims)
                .subject(JwtConstants.SUBJECT)
                .issuer(JwtConstants.ISSUER)
                .signWith(SECRET_KEY)
                .compact();

        return token;
    }

    /**
     * 解析令牌前先检查 Redis 中是否存在（未被吊销）
     *
     * @param token 令牌
     * @param secret 密钥
     * @return Claims 对象
     * @throws Exception 如果解析失败或 Token 已吊销
     */
    public static Claims parseToken(String token, String secret) throws Exception {
        try {
            // 先从 Token 中提取用户ID
            Jws<Claims> jws = Jwts.parser()
                    .verifyWith(SECRET_KEY)
                    .build()
                    .parseSignedClaims(token);

            Claims claims = jws.getPayload();
            return claims;
        } catch (JwtException e) {
            throw new Exception("Token 解析失败: " + e.getMessage());
        }
    }

    /**
     * 用户退出登录时，从 Redis 中删除 Token 实现提前失效
     *
     * @param userId 用户ID
     */
    public static void invalidateToken(Long userId) {
        String redisKey = buildRedisKey(userId);
    }

    /**
     * 构建 Redis Key（例如：auth:token:123456）
     */
    private static String buildRedisKey(Long userId) {
        return JwtConstants.TOKEN_REDIS_PREFIX + userId;
    }

    /**
     * 从 Claims 中获取用户ID
     */
    public static Long getUserIdFromClaims(Claims claims) {
        return Long.valueOf(claims.get(JwtConstants.CLAIM_USER_ID).toString());
    }
    
    /**
     * 从 token 字符串中获取用户ID
     */
    public static Long getUserIdFromToken(String token) throws Exception {
        Claims claims = parseToken(token, JwtConstants.SECRET);
        return getUserIdFromClaims(claims);
    }

    /**
     * 获取用户名
     */
    public static String getUsernameFromClaims(Claims claims) {
        return claims.getSubject();
    }

    /**
     * 获取登录用户对象
     */
    public static LoginUserVO getLoginUserFromClaims(Claims claims) {
        String userStr = (String) claims.get(JwtConstants.CLAIM_USER_KEY);
        if (userStr == null || userStr.isEmpty()) {
            return null;
        }
        return JsonUtils.parseObject(userStr, LoginUserVO.class);
    }
}